package com.coco.util;

import com.coco.enums.JdbcTypeEnums;
import com.google.common.base.CaseFormat;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class DbUtil {


    private String url;
    private String username;
    private String password;

    public DbUtil(String url,String username,String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }

    /**
     * KEY : 类名
     * VALUE ：类的包路径
     */
    private static Map<String,String> entityMap = new ConcurrentHashMap<>();

    /**
     * KEY : service接口名称
     * VALUE ：接口的包路径
     */
    private static Map<String,String> serviceMap = new ConcurrentHashMap<>();

    public Connection getConnection() throws Exception{
        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    /**
     * 获取表所有字段
     */
    public void getTableField(String packagePath) throws Exception{
        Connection connection = getConnection();
        DatabaseMetaData metaData = connection.getMetaData();
        //获取所有表
        ResultSet rs = metaData.getTables(null, "%", "%", new String[]{"TABLE"});
        Map<String,String> columnsMap = null;
        while(rs.next()) {
            //获取表名字
            String table_name = rs.getString("TABLE_NAME");
            System.out.println("表明是：" + table_name);
            columnsMap = new HashMap<>();
            ResultSet columns = metaData.getColumns(null, "%", rs.getString("TABLE_NAME"), "%");
            while(columns.next()) {
                String column_name = columns.getString("COLUMN_NAME");
                String type_name = columns.getString("TYPE_NAME");
                System.out.println("列名是：" + column_name + "， 类型是：" + type_name);
                columnsMap.put(column_name,type_name);
            }
            System.out.println(" =====================");
            createEntity(table_name,columnsMap,packagePath);
            createMapper(table_name,packagePath);
            createService(table_name,packagePath);
            createServiceImpl(table_name,packagePath);
            createController(table_name,packagePath);
        }
    }

    /**
     * 生成实体类
     * @param tableName
     * @param columns
     * @param packagePath
     */
    public static void createEntity(String tableName, Map<String,String> columns,String packagePath) {
        FileWriter fileWriter = null;
        BufferedWriter out = null;
        String tableParse = null;
        try{
            //获取当前项目的根路径，最后的文件都会保存到根路径/data/ 目录下
            String path = DbUtil.class.getResource("/").getPath();
            String replacePath = path.replace("target/classes/", "data/entity/");
            StringBuilder entityBuilder = new StringBuilder();
            StringBuilder entityPathBuilder = new StringBuilder();
            //将表名进行驼峰转换成类名  import com.lantuo.entity.FileContent;
            tableParse = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            entityBuilder.append(replacePath).append(tableParse).append(".java");
            fileWriter = new FileWriter(entityBuilder.toString());
            out = new BufferedWriter(fileWriter);
            StringBuilder stringBuilder = new StringBuilder();
            entityPathBuilder.append("import ").append(packagePath).append(".entity").append(".").append(tableParse).append("; \n");
            stringBuilder.append(String.format("package %s",packagePath)).append(".entity; \n\n");
            if(columns.containsValue("DATE") || columns.containsValue("DATETIME") ||
                    columns.containsValue("TIMESTAMP") || columns.containsValue("TIME")) {
                stringBuilder.append("import java.util.Date; \n");
            }
            stringBuilder.append("import lombok.Data; \n\n");
            stringBuilder.append("@Data \n");
            stringBuilder.append("public class ").append(tableParse).append("{ \n");
            if(!columns.isEmpty()) {
                for(String columnName : columns.keySet()) {
                    //将列名称进行驼峰装换
                    String parseColumnName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, columnName);
                    //获取名称类型
                    String column_type = columns.get(columnName);
                    String type = JdbcTypeEnums.getVal(column_type);
                    stringBuilder.append("     private ").append(type).append(" ").append(parseColumnName).append("; \n");
                }
            }
            stringBuilder.append("} \n");
            out.write(stringBuilder.toString());
            entityMap.put(tableParse,entityPathBuilder.toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成对应的Mapper文件
     * @param tableName
     * @param packagePath
     */
    public static void createMapper(String tableName,String packagePath) {
        FileWriter fileWriter = null;
        BufferedWriter out = null;
        try{
            //获取当前项目的根路径，最后的文件都会保存到根路径/data/ 目录下
            String path = DbUtil.class.getResource("/").getPath();
            String replacePath = path.replace("target/classes/", "data/mapper/");
            StringBuilder entityBuilder = new StringBuilder();
            //将表名进行驼峰转换
            String tableParse = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            entityBuilder.append(replacePath).append(tableParse).append("Mapper").append(".java");
            fileWriter = new FileWriter(entityBuilder.toString());
            out = new BufferedWriter(fileWriter);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(String.format("package %s",packagePath)).append(".mapper; \n");
            stringBuilder.append("import org.apache.ibatis.annotations.Mapper; \n");
            stringBuilder.append("import com.baomidou.mybatisplus.core.mapper.BaseMapper; \n");
            if(entityMap.containsKey(tableParse)) {
                stringBuilder.append(entityMap.get(tableParse));
            }
            stringBuilder.append("@Mapper \n");
            stringBuilder.append("public interface ").append(tableParse).append("Mapper extends BaseMapper<").append(tableParse).append(">").append("{ \n");
            stringBuilder.append("} \n");
            out.write(stringBuilder.toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成对应的Service接口
     * @param tableName
     * @param packagePath
     */
    public static void createService(String tableName,String packagePath) {
        FileWriter fileWriter = null;
        BufferedWriter out = null;
        try{
            //获取当前项目的根路径，最后的文件都会保存到根路径/data/ 目录下
            String path = DbUtil.class.getResource("/").getPath();
            String replacePath = path.replace("target/classes/", "data/service/");
            StringBuilder entityBuilder = new StringBuilder();
            //将表名进行驼峰转换
            String tableParse = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            String param = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName);
            entityBuilder.append(replacePath).append(tableParse).append("Service").append(".java");
            fileWriter = new FileWriter(entityBuilder.toString());
            out = new BufferedWriter(fileWriter);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(String.format("package %s",packagePath)).append(".service; \n");
            if(entityMap.containsKey(tableParse)) {
                stringBuilder.append(entityMap.get(tableParse));
            }
            stringBuilder.append("import java.util.List; \n");
            stringBuilder.append("import ").append(packagePath).append(".entity.").append(tableParse).append("; \n\n");
            stringBuilder.append("public interface ").append(tableParse).append("Service").append("{ \n\n");

            //开始新增添加方法
            stringBuilder.append("      void add(").append(tableParse).append(" ").append(param).append("); \n\n");
            stringBuilder.append("      void edit(").append(tableParse).append(" ").append(param).append("); \n\n");
            stringBuilder.append("      List<").append(tableParse).append("> queryPage(Integer pageNo, Integer pageSize); \n\n");
            stringBuilder.append("      void delById(Integer id); \n\n");
            stringBuilder.append("      ").append(tableParse).append(" getById(Integer id); \n\n");
            stringBuilder.append("} \n");
            out.write(stringBuilder.toString());
            StringBuilder mapBuilder = new StringBuilder();
            mapBuilder.append(packagePath).append(".service.").append(tableParse).append("Service;\n");
            serviceMap.put(tableParse,mapBuilder.toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成实现类
     * @param tableName
     * @param packagePath
     */
    public static void createServiceImpl(String tableName,String packagePath) {
        FileWriter fileWriter = null;
        BufferedWriter out = null;
        try{
            //获取当前项目的根路径，最后的文件都会保存到根路径/data/ 目录下
            String path = DbUtil.class.getResource("/").getPath();
            String replacePath = path.replace("target/classes/", "data/impl/");
            StringBuilder entityBuilder = new StringBuilder();
            //将表名进行驼峰转换
            String tableParse = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            String param = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName);
            entityBuilder.append(replacePath).append(tableParse).append("ServiceImpl").append(".java");
            fileWriter = new FileWriter(entityBuilder.toString());
            out = new BufferedWriter(fileWriter);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(String.format("package %s",packagePath)).append(".service.impl; \n");
            if(serviceMap.containsKey(tableParse)) {
                stringBuilder.append("import ").append(serviceMap.get(tableParse));
            }
            if(entityMap.containsKey(tableParse)) {
                stringBuilder.append(entityMap.get(tableParse));
            }
            stringBuilder.append("import ").append(packagePath).append(".entity.").append(tableParse).append("; \n");
            stringBuilder.append("import java.util.List; \n");
            stringBuilder.append("import org.springframework.beans.factory.annotation.Autowired; \n");
            stringBuilder.append("import org.springframework.stereotype.Service; \n");
            stringBuilder.append("import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; \n");
            stringBuilder.append("import com.baomidou.mybatisplus.extension.plugins.pagination.Page; \n");
            stringBuilder.append("import com.coco.mapper.").append(tableParse).append("Mapper; \n\n");
            stringBuilder.append("@Service \n");
            stringBuilder.append("public class ").append(tableParse).append("ServiceImpl implements ").append(tableParse).append("Service").append("{ \n\n");
            //添加依赖
            stringBuilder.append("      private ").append(tableParse).append("Mapper ").append(param).append("Mapper; \n\n");
            stringBuilder.append("      @Autowired \n");
            stringBuilder.append("      public ").append(tableParse).append("ServiceImpl(").append(tableParse).append("Mapper ").append(param).append("Mapper) { \n");
            stringBuilder.append("             this.").append(param).append("Mapper = ").append(param).append("Mapper; \n").append("} \n\n");

            //添加方法
            stringBuilder.append("\n\n");
            stringBuilder.append("      @Override \n");
            stringBuilder.append("      public List<").append(tableParse).append("> queryPage(Integer pageNo, Integer pageSize) { \n");
            stringBuilder.append("             Page<").append(tableParse).append("> page = ").append(param)
                    .append("Mapper.selectPage(new Page<>(pageNo, pageSize), new QueryWrapper<")
                    .append(tableParse).append(">()); \n");
            stringBuilder.append("             List<").append(tableParse).append("> recodes = page.getRecords(); \n");
            stringBuilder.append("             return recodes; \n");
            stringBuilder.append("      } \n");

            stringBuilder.append("\n\n");
            stringBuilder.append("      @Override \n");
            stringBuilder.append("      public void add(").append(tableParse).append(" ").append(param).append("){ \n");
            stringBuilder.append("             ").append(param).append("Mapper.insert(").append(param).append("); \n").append("      } \n\n\n");

            stringBuilder.append("      @Override \n");
            stringBuilder.append("      public void edit(").append(tableParse).append(" ").append(param).append("){ \n");
            stringBuilder.append("             ").append(param).append("Mapper.updateById(").append(param).append("); \n").append("      } \n\n\n");

            stringBuilder.append("      @Override \n");
            stringBuilder.append("      public void delById(Integer id){ \n");
            stringBuilder.append("             ").append(param).append("Mapper.deleteById(id); \n").append("      } \n\n\n");

            stringBuilder.append("      @Override \n");
            stringBuilder.append("      public ").append(tableParse).append(" getById(Integer id) { \n");
            stringBuilder.append("              return ").append(param).append("Mapper.selectById(id); \n").append("      } \n");

            stringBuilder.append("} \n");
            out.write(stringBuilder.toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成控制器
     * @param tableName
     * @param packagePath
     */
    public static void createController(String tableName,String packagePath) {
        FileWriter fileWriter = null;
        BufferedWriter out = null;
        try{
            //获取当前项目的根路径，最后的文件都会保存到根路径/data/ 目录下
            String path = DbUtil.class.getResource("/").getPath();
            String replacePath = path.replace("target/classes/", "data/controller/");
            StringBuilder entityBuilder = new StringBuilder();
            //将表名进行驼峰转换
            String tableParse = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            String param = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName);
            entityBuilder.append(replacePath).append(tableParse).append("Controller").append(".java");
            fileWriter = new FileWriter(entityBuilder.toString());
            out = new BufferedWriter(fileWriter);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(String.format("package %s",packagePath)).append(".controller; \n");
            if(serviceMap.containsKey(tableParse)) {
                stringBuilder.append("import ").append(serviceMap.get(tableParse));
            }
            if(entityMap.containsKey(tableParse)) {
                stringBuilder.append(entityMap.get(tableParse));
            }
            stringBuilder.append("import java.util.List; \n");
            stringBuilder.append("import org.springframework.beans.factory.annotation.Autowired; \n");
            stringBuilder.append("import org.springframework.web.bind.annotation.*; \n\n\n");
            stringBuilder.append("@RestController \n");
            stringBuilder.append("@RequestMapping(\"/").append(param).append("\") \n");
            stringBuilder.append("public class ").append(tableParse).append("Controller{ \n\n\n");
            //添加依赖
            stringBuilder.append("      private ").append(tableParse).append("Service ").append(param).append("Service; \n\n\n");
            stringBuilder.append("      @Autowired \n");
            stringBuilder.append("      public ").append(tableParse).append("Controller(").append(tableParse).append("Service ").append(param).append("Service) { \n");
            stringBuilder.append("              this.").append(param).append("Service = ").append(param).append("Service; \n").append("      } \n");

            //添加方法
            stringBuilder.append("\n\n");
            stringBuilder.append("      @GetMapping(\"/queryPage\") \n");
            stringBuilder.append("      public List<").append(tableParse).append("> queryPage(@RequestParam(name=\"pageNo\", defaultValue=\"1\") Integer pageNo,@RequestParam(name=\"pageSize\", defaultValue=\"50\") Integer pageSize) { \n");
            stringBuilder.append("             List<").append(tableParse).append("> recodes = ").append(param).append("Service.queryPage(pageNo,pageSize); \n");
            stringBuilder.append("             return recodes; \n");
            stringBuilder.append("      } \n");

            stringBuilder.append("\n\n");
            stringBuilder.append("      @PostMapping(\"/add\") \n");
            stringBuilder.append("      public void add(@RequestBody ").append(tableParse).append(" ").append(param).append("){ \n");
            stringBuilder.append("             ").append(param).append("Service.add(").append(param).append("); \n").append("      } \n\n\n");

            stringBuilder.append("      @PutMapping(\"/edit\") \n");
            stringBuilder.append("      public void edit(@RequestBody ").append(tableParse).append(" ").append(param).append("){ \n");
            stringBuilder.append("             ").append(param).append("Service.edit(").append(param).append("); \n").append("      } \n\n\n");

            stringBuilder.append("      @DeleteMapping(\"/delById\") \n");
            stringBuilder.append("      public void delById(@RequestParam(name=\"id\") Integer id){ \n");
            stringBuilder.append("             ").append(param).append("Service.delById(id); \n").append("      } \n");
            stringBuilder.append("} \n");
            out.write(stringBuilder.toString());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
